package com.alipay.rebate.shop.controller.customer;

import com.alipay.rebate.shop.constants.MobileCodeMapper;
import com.alipay.rebate.shop.constants.RedisConstant;
import com.alipay.rebate.shop.constants.PatternContant;
import com.alipay.rebate.shop.constants.StatusCode;
import com.alipay.rebate.shop.core.ResultGenerator;
import com.alipay.rebate.shop.dao.mapper.AppSettingsMapper;
import com.alipay.rebate.shop.dao.mapper.Coun2numMapper;
import com.alipay.rebate.shop.dao.mapper.MobileCodeInformationMapper;
import com.alipay.rebate.shop.dao.mapper.UserMapper;
import com.alipay.rebate.shop.helper.HistoryPriceHelper;
import com.alipay.rebate.shop.helper.InterfaceStatisticsHelper;
import com.alipay.rebate.shop.helper.MobileCodeInformationHelper;
import com.alipay.rebate.shop.model.AppSettings;
import com.alipay.rebate.shop.model.Coun2num;
import com.alipay.rebate.shop.model.MobileCodeInformation;
import com.alipay.rebate.shop.pojo.appsettings.AppSettingsRsp;
import com.alipay.rebate.shop.pojo.appsettings.PrivacyPolicy;
import com.alipay.rebate.shop.pojo.historyprice.ResultResp;
import com.alipay.rebate.shop.pojo.mobilecode.SendSmsResponse;
import com.alipay.rebate.shop.service.customer.CustomerUserService;
import com.alipay.rebate.shop.utils.AliUtil;
import com.alipay.rebate.shop.model.User;
import com.alipay.rebate.shop.pojo.common.ResponseResult;

import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import com.alipay.rebate.shop.utils.HttpUtils;
import com.alipay.rebate.shop.utils.IpUtil;
import com.alipay.rebate.shop.utils.QiniuUtil;
import com.aliyuncs.CommonResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;


@Controller
public class NoTokenController {

    private final Logger logger = LoggerFactory.getLogger(NoTokenController.class);

    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    CustomerUserService userService;
    @Autowired
    UserMapper userMapper;
    @Autowired
    AppSettingsMapper appSettingsMapper;
    @Autowired
    MobileCodeInformationMapper informationMapper;
    @Autowired
    MobileCodeInformationHelper informationHelper;
    @Resource
    InterfaceStatisticsHelper interfaceStatisticsHelper;
    @Resource
    HistoryPriceHelper historyPriceHelper;
    @Resource
    Coun2numMapper coun2numMapper;
    @Resource
    MobileCodeInformationHelper mobileCodeInformationHelper;

    CopyOnWriteArrayList<ConcurrentHashMap<String,Long>> ipList = new CopyOnWriteArrayList<>();
    /**
     * 发送验证码，用于登陆
     * @param phone
     * @return
     */
    @GetMapping("/common/generateMobileVerificationCode")
    @ResponseBody
    public ResponseResult<String> generateMobileVerificationCode(
            @NotNull(message = PatternContant.PHONE_NULL_MESSAGE)
            @Pattern(regexp= PatternContant.PHONE_PATTERN,
                    message=PatternContant.PHONE_PATTERN_ERROR_MESSAGE)
            String phone, HttpServletRequest request
    ){

        logger.debug("phone received from request is : {}",phone);

        // 生成六位数字验证码
        String mobileCode = generateMobileCode();
        logger.debug("mobileCode is : {}",mobileCode);
        String key = RedisConstant.MOBILE_CODE_CUSTOMER_NO_LOGIN_PREFIX + phone;
        logger.debug("key is : {}",key);
        int type = MobileCodeMapper.getRedisValidCodeValuePrefixByKey(RedisConstant.MOBILE_CODE_CUSTOMER_NO_LOGIN_PREFIX);
        MobileCodeInformation information = informationHelper.getMobileCodeInformation(phone,type,mobileCode);
        ResponseResult<String> responseResult = new ResponseResult<>();
        // 发送验证码
        try {

            limitAccessFrequency(request,phone);

            // 先往redis存放验证码信息，再发送给客户
            stringRedisTemplate.opsForValue().set(key,mobileCode,RedisConstant.MOBILE_CODE_CUSTOMER_TIME_OUT, TimeUnit.MINUTES);
            logger.debug("mobileCode is : {}",stringRedisTemplate.opsForValue().get(key));
            SendSmsResponse commonResponse = AliUtil.sendSms(phone, mobileCode);
            mobileCodeInformationHelper.insertMobileCodeInformation(commonResponse,information);
            logger.debug("redis key is : {}, value is : {}",key,phone);
            // 放入redis，半个小时过期
            responseResult.setData(mobileCode);
            interfaceStatisticsHelper.getCount("generateMobileVerificationCode");
            return responseResult;
        } catch (Exception e) {
            logger.debug("sending sms code failed,{}",e);

            //短信发送失败
            information.setStatus(2l);
            informationMapper.insertMobileCodeInformation(information);

            responseResult.setStatus(StatusCode.MOBILE_CODE_SEND_ERROR.getCode());
            stringRedisTemplate.delete(key);
            if (e instanceof RuntimeException){
                responseResult.setData("请求过于频繁");
                return responseResult;
            }
            return responseResult;
        }
    }


    /**
     * 发送验证码，用于登陆
     * @param phone
     * @return
     */
    @GetMapping("/common/generateInternationalMobileVerificationCode")
    @ResponseBody
    public ResponseResult<String> generateInternationalMobileVerificationCode(
            @NotNull(message = PatternContant.PHONE_NULL_MESSAGE)
                    String phone,String areaCode, HttpServletRequest request
    ){
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(areaCode);
        stringBuilder.append(phone);
        // 生成六位数字验证码
        String mobileCode = generateMobileCode();
        logger.debug("mobileCode is : {}",mobileCode);
        String key = RedisConstant.MOBILE_CODE_CUSTOMER_NO_LOGIN_PREFIX + phone;
        logger.debug("key is : {}",key);
        int type = MobileCodeMapper.getRedisValidCodeValuePrefixByKey(RedisConstant.MOBILE_CODE_CUSTOMER_NO_LOGIN_PREFIX);
        MobileCodeInformation information = informationHelper.getMobileCodeInformation(phone,type,mobileCode);
        ResponseResult<String> responseResult = new ResponseResult<>();
        // 发送验证码
        try {

            limitAccessFrequency(request,phone);

            // 先往redis存放验证码信息，再发送给客户
            stringRedisTemplate.opsForValue().set(key,mobileCode,RedisConstant.MOBILE_CODE_CUSTOMER_TIME_OUT, TimeUnit.MINUTES);
            logger.debug("mobileCode is : {}",stringRedisTemplate.opsForValue().get(key));
            SendSmsResponse commonResponse = AliUtil.sendInternationalSms(stringBuilder.toString(), mobileCode);
            mobileCodeInformationHelper.insertMobileCodeInformation(commonResponse,information);
            logger.debug("redis key is : {}, value is : {}",key,phone);
            // 放入redis，半个小时过期
            responseResult.setData(mobileCode);
            return responseResult;
        } catch (Exception e) {
            logger.debug("sending sms code failed,{}",e);

            //短信发送失败
            information.setStatus(2l);
            informationMapper.insertMobileCodeInformation(information);

            responseResult.setStatus(StatusCode.MOBILE_CODE_SEND_ERROR.getCode());
            stringRedisTemplate.delete(key);
            if (e instanceof RuntimeException){
                responseResult.setData("请求过于频繁");
                return responseResult;
            }
            return responseResult;
        }
    }



    private void limitAccessFrequency(HttpServletRequest request,String phone){
        //限制访问频率
        String userIp = IpUtil.getIpAddress(request);

        logger.debug("limitAccessFrequency userIp is : {}",userIp);
        ConcurrentHashMap<String,Long> ipMap = new ConcurrentHashMap<>();
        if(ipList!=null && !ipList.isEmpty()){
            for(ConcurrentHashMap<String,Long> myMap : ipList) {
                if(myMap.get(userIp) != null) {
                    //同一IP15秒内只能提交一次
                    if(System.currentTimeMillis() - myMap.get(userIp) < 15 * 1000){
                        myMap.put(phone,System.currentTimeMillis());
                        throw new RuntimeException("请求过于频繁");
                    }
                }
            }
            if(ipList.size()==10) {
                // 放满10次请求 清空一次
                ipList.clear();
            }
        }
        ipMap.put(userIp,System.currentTimeMillis());
        ipList.add(ipMap);
        logger.debug("limitAccessFrequency ipList is : {}",ipList);
        logger.debug("limitAccessFrequency ipMap is : {}",ipMap);
    }

    /**
     * 生成六位验证码
     * @return
     */
    public String generateMobileCode(){
        String mobileCode = String.valueOf((int)((Math.random()*9+1)*100000));
        return mobileCode;
    }

    @GetMapping("/common/getAppSettings")
    @ResponseBody
    public ResponseResult<List<AppSettingsRsp>> getAppSettings(){
        ResponseResult<List<AppSettings>> responseResult = new ResponseResult<>();
        List<AppSettings> appSettings = appSettingsMapper.selectAll();
        List<AppSettingsRsp> appSettingsRspList = new ArrayList<>();
        for (AppSettings appSetting : appSettings){
            AppSettingsRsp appSettingsRsp = new AppSettingsRsp();
            appSettingsRsp.setSpDomainType(appSetting.getSpDomainType());
            appSettingsRsp.setSpDomain(appSetting.getSpDomain());
            appSettingsRsp.setPid(appSetting.getPid());
            appSettingsRsp.setIsShowRebate(appSetting.getIsShowRebate());
            appSettingsRsp.setIosAudit(appSetting.getIosAudit());
            appSettingsRsp.setId(appSetting.getId());
            appSettingsRsp.setCsWetchat(appSetting.getCsWetchat());
            appSettingsRsp.setAppVersion(appSetting.getAppVersion());
            appSettingsRsp.setActivityPid(appSetting.getActivityPid());
            appSettingsRsp.setUpdateTime(appSetting.getUpdateTime());
            appSettingsRsp.setHaodankuKey(appSetting.getHaodankuKey());
            appSettingsRsp.setJdRebate(appSetting.getJdRebate());
            appSettingsRsp.setPddRebate(appSetting.getPddRebate());
            appSettingsRsp.setPromoteEarn(appSetting.getPromoteEarn());
            appSettingsRsp.setPrivacyPolicy(appSetting.getPrivacyPolicy());
            appSettingsRsp.setUseAgreement(appSetting.getUseAgreement());
            appSettingsRsp.setTaobaoKey(appSetting.getTaobaoAppKey());
            appSettingsRsp.setAndroidAudit(appSetting.getAndroidAudit());
            appSettingsRsp.setAndroidAppVersion(appSetting.getAndroidAppVersion());
            appSettingsRspList.add(appSettingsRsp);
        }
        return ResultGenerator.genSuccessResponseResult(appSettingsRspList);
    }

    @GetMapping("/common/getPrivacyPolicy")
    @ResponseBody
    public ResponseResult<List<PrivacyPolicy>> getPrivacyPolicy(){
        List<AppSettings> appSettings = appSettingsMapper.selectAll();
        List<PrivacyPolicy> appSettingsRspList = new ArrayList<>();
        for (AppSettings appSetting : appSettings){
            PrivacyPolicy appSettingsRsp = new PrivacyPolicy();
            appSettingsRsp.setPrivacyPolicy(appSetting.getPrivacyPolicy());
            appSettingsRsp.setUseAgreement(appSetting.getUseAgreement());
            appSettingsRspList.add(appSettingsRsp);
        }
        return ResultGenerator.genSuccessResponseResult(appSettingsRspList);
    }

    @GetMapping("/common/getQiNiuYunUploadToken")
    @ResponseBody
    public ResponseResult<String> getQiNiuYunUploadToken(){
        String token = QiniuUtil.getQiniuUploadToken();
        return ResultGenerator.genSuccessResponseResult(token);
    }

    @GetMapping("/common/getHistoryMoney")
    @ResponseBody
    public Object getHistoryPrice(Long id, Integer type) throws IOException {
        Object obj = historyPriceHelper.getHistoryPrice(id, type);
        interfaceStatisticsHelper.getCount("getHistoryMoney");
        return obj;
    }

    /**
     * 获取用户信息
     * @return
     */
    @GetMapping("/common/getUserInfoForTest")
    @ResponseBody
    public ResponseResult<User> getUserInfoForTest(String phone){
        return userService.selectAllUserInfoForTestByPhone(phone);
    }

    /**
     * 获取用户信息
     * @return
     */
    @GetMapping("/common/getUserInfoForTest1")
    @ResponseBody
    public User getUserInfoForTest1(Long id){
        return userMapper.selectById(id);
    }


    /**
     * 获取用户信息
     * @return
     */
    @DeleteMapping("/common/deleteUserForTest")
    @ResponseBody
    public ResponseResult<Void> deleteUserForTest(String phone){
        return userService.deleteUserInfoForTestByPhone(phone);
    }

    /**
     * 获取用户信息
     * @return
     */
    @GetMapping("/common/test")
    @ResponseBody
    public ResponseResult test(HttpServletRequest request) throws Exception {
        String ipAddress = IpUtil.getIpAddress(request);
        String ipAddr = IpUtil.getIpAddr(request);
        String getIp = IpUtil.getIpAddr(request);
        logger.debug("limitAccessFrequency ipAddr is : {}",ipAddr);
        Map<String,String> test = new HashMap<>();
        test.put("ipAddress",ipAddress);
        test.put("ipAddr",ipAddr);
        test.put("getIp",getIp);
        return ResultGenerator.genSuccessResponseResult(test);
    }

    @GetMapping("/common/getCoun2num")
    @ResponseBody
    public ResponseResult list(){
        List<Coun2num> coun2nums = coun2numMapper.selectAll();
        return ResultGenerator.genSuccessResponseResult(coun2nums);
    }

}
